package org.osomit.sacct.security.otp.impl;

import org.osomit.sacct.security.otp.iface.OTPTokenReader;
import org.osomit.sacct.security.otp.iface.OTPTokenWriter;
import org.osomit.sacct.security.otp.iface.OTPToken;
import org.osomit.sacct.security.utils.SymmetricCipher;
import org.osomit.sacct.security.utils.Serializer;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;

import org.apache.commons.codec.binary.Base64;

/**
 * Read and write the OTP Token to a file
 * 
 * @author Jian Fang (John.Jian.Fang@gmail.com)
 *
 * Date: Jun 26, 2009
 */
public class FileOTPTokenReaderWriter implements OTPTokenReader, OTPTokenWriter {
	static int TYPICAL_SIZE = 512;

	//the file name to store the token
	private String fileName;

	//the password to encode the token using DES
	private String password;


	public final String getFileName() {
		return fileName;
	}

	public final void setFileName(String fileName) {
		this.fileName = fileName;
	}

	public final String getPassword() {
		return password;
	}

	public final void setPassword(String password) {
		this.password = password;
	}

	public void write(OTPToken token) throws Exception {
		if(this.fileName == null || token == null || this.password == null)
			return;

		byte[] serialized = Serializer.serializeAndCompress(token, true);
		byte[] encrypted = SymmetricCipher.desEncrypt(password, serialized);
		String result = new String(Base64.encodeBase64(encrypted), "UTF8");

		FileOutputStream fout = new FileOutputStream(this.fileName, false);
		fout.write(result.getBytes());
		fout.close();
	}

	public OTPToken read() throws Exception {
		if(this.fileName == null || this.password == null)
			return null;

		FileInputStream fin = new FileInputStream (this.fileName);
		BufferedReader br = new BufferedReader(new InputStreamReader(fin));
		StringBuffer sb = new StringBuffer(TYPICAL_SIZE);
		String line = null;
		while((line = br.readLine()) != null){
			sb.append(line);
		}

		fin.close();
		br.close();

		byte[] encrypted = Base64.decodeBase64(sb.toString().getBytes());
		byte[] decrypted = SymmetricCipher.desDecrypt(this.password, encrypted);
		OTPToken token = (OTPToken)Serializer.decompressAndDeserialize(decrypted, false);

		return token;
	}

}
